Nouns DAO × Octant v2

Integration Plan

Overview

Nouns DAO will integrate with Octant v2 through the Lido Yield Skimming Strategy — an ERC-4626 vault that captures yield from wstETH exchange rate appreciation (~3-5% APY from ETH staking rewards).

Component Purpose Capital
Lido Yield Skimming Strategy Generate yield for public goods funding wstETH held by treasury

Architecture Note: The strategy IS the ERC-4626 vault. No MultistrategyVault wrapper is needed since only one strategy is approved by the DAO. This simplifies deployment, reduces gas costs, and eliminates unnecessary complexity.

Prerequisites (Pending Items)

The following items must be resolved before executing the DAO proposal:

Item Status Owner Notes
Dragon Funding Pool address ⏳ Pending Nouns DAO Strategy donation recipient (PaymentSplitter)
Keeper Bot address ⏳ Pending Nouns DAO Strategy keeper for harvesting
Emergency Shutdown Admin address ⏳ Pending Nouns DAO Can shutdown strategy and perform emergency withdrawals
wstETH deposit amount ⏳ Pending Nouns DAO Amount of wstETH to deposit (treasury holds ~1,725 wstETH)

⚠️ Action Required: Update this document with actual addresses before submitting the proposal.

Verified On-Chain Addresses

Entity Address Network
Nouns DAO Treasury (Executor/Timelock) 0xb1a32FC9F9D8b2cf86C068Cae13108809547ef71 Ethereum
Nouns DAO Governor Proxy 0x6f3E6272A167e8AcCb32072d08E0957F9c79223d Ethereum
Nouns NFT Token 0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03 Ethereum
wstETH 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 Ethereum
PaymentSplitter Factory 0x5711765E0756B45224fc1FdA1B41ab344682bBcb Ethereum
Tokenized Strategy Implementation 0x8cf7246a74704bBE59c9dF614ccB5e3d9717d8Ac Ethereum

Lido Yield Skimming Strategy

The LidoStrategy is an ERC-4626 vault (via Yearn's TokenizedStrategy) that tracks wstETH → stETH exchange rate appreciation. Treasury deposits wstETH directly into the strategy.

Underlying Yield Source

wstETH (Wrapped Staked ETH) — Lido's non-rebasing wrapper around stETH.

  • Mechanism: Exchange rate increases as staking rewards accrue to stETH
  • Rate Source: wstETH.stEthPerToken() (manipulation-resistant, oracle-free)
  • Yield: ~3-5% APY from ETH validator staking rewards
  • Risk: ETH validator slashing can reduce exchange rate

Yield Capture Mechanism

┌──────────────────────────────────────────────────────────────────────────────┐ │ 1. User deposits 100 wstETH at rate 1.0 (100 stETH value) │ │ │ │ │ ▼ │ │ 2. Exchange rate increases to 1.05 (ETH staking rewards) │ │ - Vault value: 100 wstETH × 1.05 = 105 stETH value │ │ - User debt: 100 stETH value │ │ - Profit: 5 stETH value │ │ │ │ │ ▼ │ │ 3. On report(), strategy mints 5 value-shares to Dragon Router │ │ - User can still redeem 100 stETH value worth of wstETH │ │ - Dragon Router receives yield without diluting user │ └──────────────────────────────────────────────────────────────────────────────┘

Role Assignments

Role Assigned To Description
Management Nouns DAO Treasury (0xb1a3...ef71) Administrative role (set keeper, set emergency admin, shutdown)
Keeper Dedicated Bot/EOA REQUIRED: Authorized to call report() to harvest yields without governance votes
Emergency Admin Nouns DAO Treasury (0xb1a3...ef71) Can shutdown the strategy and perform emergency withdrawals

Critical: The Keeper should be a dedicated EOA or bot, NOT the Treasury. Assigning Keeper to Treasury would require a governance vote for every harvest (7+ day minimum voting cycle), creating severe operational bottlenecks.

Yield Distribution

Destination Allocation
Dragon Funding Pool 100%

PaymentSplitter (Dragon Funding Pool)

The PaymentSplitter is deployed via the existing factory and receives yield from the strategy.

Recommended Configuration

Payee Allocation Purpose
Nouns Ecosystem Grants 100% Public goods funding

Note: Multiple payees with different allocations can be configured if desired (e.g., 80% grants, 20% operations).

Nouns DAO Governance

Architecture

Nouns DAO uses a Governor + Timelock pattern with NFT-based voting:

Component Address / Value
Governor Proxy 0x6f3E6272A167e8AcCb32072d08E0957F9c79223d
Executor (Timelock) 0xb1a32FC9F9D8b2cf86C068Cae13108809547ef71
Voting Token Nouns NFT (0x9C8fF314...DC03)

Execution Call Chain

┌──────────────────────────────────────────────────────────────────────────────┐ │ Step 1: Any EOA calls Governor to execute passed proposal │ │ execute(targets[], values[], calldatas[], descriptionHash) │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ Nouns DAO Governor (0x6f3E6272A167e8AcCb32072d08E0957F9c79223d) │ │ │ └────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ Step 2: Governor triggers queued transaction on Timelock │ │ execute(target, value, data, predecessor, salt) │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ Executor / Timelock (0xb1a32FC9F9D8b2cf86C068Cae13108809547ef71) │ │ │ └────────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ Step 3: Timelock executes transaction to target contract │ │ msg.sender = Timelock (0xb1a3...) │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────────────┐ │ │ │ Target Contract (Factory / wstETH / Strategy) │ │ │ └────────────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────┘

Critical: From the target contract's perspective, msg.sender is the Executor/Timelock address (0xb1a3...), NOT the Governor. This is why all roles are assigned to the Executor address.

Governance Parameters

See current governance parameters on nouns.wtf/vote.

Voting Platforms

Platform Type Use Case
nouns.wtf/vote On-chain Treasury transactions, contract interactions
Discourse Forum Discussion, temperature checks

Execution Playbook

Phase 1: PaymentSplitter Deployment

Deploy a PaymentSplitter to receive yield from the strategy.

Phase 2: Strategy Deployment

The deployment can be executed in a single DAO proposal with 4 batched transactions:

  1. Deploy PaymentSplitter via Factory
  2. Deploy LidoStrategy via Factory
  3. Approve wstETH to Strategy
  4. Deposit wstETH into Strategy

Note: The strategy factory uses CREATE2, allowing address precomputation.

Note: LidoStrategyFactory needs to be deployed to mainnet first.

Gas Profile

Component Gas Cost
PaymentSplitter Deployment ~50k
LidoStrategy Deployment ~3-4M
wstETH Approve ~50k
wstETH Deposit ~200k
Total (batched) ~4M
Block Gas Limit 30M
Headroom >85%

Transaction Details

Transaction 1: Deploy PaymentSplitter

Target:   0x5711765E0756B45224fc1FdA1B41ab344682bBcb (PaymentSplitter Factory)
Function: createPaymentSplitter(address[],string[],uint256[])
Selector: 0x... (TBD)
Value:    0

Parameters:
  payees:     [[GRANT_RECIPIENT_ADDRESS]]
  payeeNames: ["NounsGrants"]
  shares:     [100]

Transaction 2: Deploy Strategy

Target:   [LIDO_STRATEGY_FACTORY_ADDRESS]
Function: createStrategy(string,address,address,address,address,bool,address)
Selector: 0x... (TBD)
Value:    0

Parameters:
  _name:                     "NounsLidoStrategy"
  _management:               0xb1a32FC9F9D8b2cf86C068Cae13108809547ef71
  _keeper:                   [KEEPER_ADDRESS] (dedicated bot)
  _emergencyAdmin:           [EMERGENCY_ADMIN_ADDRESS]
  _donationAddress:          [PAYMENT_SPLITTER_ADDRESS]
  _enableBurning:            false
  _tokenizedStrategyAddress: 0x8cf7246a74704bBE59c9dF614ccB5e3d9717d8Ac

Transaction 3: Approve wstETH

Target:   0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 (wstETH)
Function: approve(address,uint256)
Selector: 0x095ea7b3
Value:    0

Parameters:
  spender: [STRATEGY_ADDRESS] (from Tx 2)
  amount:  [DEPOSIT_AMOUNT] (e.g., 1000000000000000000000 for 1000 wstETH)

Transaction 4: Deposit wstETH

Target:   [STRATEGY_ADDRESS] (from Tx 2)
Function: deposit(uint256,address)
Selector: 0x6e553f65
Value:    0

Parameters:
  assets:   [DEPOSIT_AMOUNT] (e.g., 1000000000000000000000 for 1000 wstETH)
  receiver: 0xb1a32FC9F9D8b2cf86C068Cae13108809547ef71 (Treasury)

Generate Calldata

forge script partners/nouns_dao/script/GenerateProposalCalldata.s.sol --fork-url $ETH_RPC_URL -vvvv

Post-Deployment Operations

Harvest Operation

Target:   [STRATEGY_ADDRESS]
Function: report()
Selector: 0x2606a10b
Value:    0

Calldata: 0x2606a10b

Note: Called by management or keeper to harvest yield. Returns (uint256 profit, uint256 loss).
Mints profit shares to Dragon Router (PaymentSplitter).

Release Yield from PaymentSplitter

Target:   [PAYMENT_SPLITTER_ADDRESS]
Function: release(address token, address account)
Selector: 0x... (TBD)
Value:    0

Parameters:
  token:   [STRATEGY_ADDRESS]
  account: [PAYEE_ADDRESS]

Note: Payee calls to claim their share of accumulated yield.

Emergency Operations

Shutdown Strategy

Target:   [STRATEGY_ADDRESS]
Function: shutdownStrategy()
Selector: 0xbe8f1668

Effect: Stops new deposits/mints, allows withdrawals.
Access:  management or emergencyAdmin

Emergency Withdraw

Target:   [STRATEGY_ADDRESS]
Function: emergencyWithdraw(uint256)
Selector: 0x5312ea8e

Parameters:
  _amount: Amount to withdraw (up to full balance)

Prerequisite: Strategy must be shutdown first.
Access:       management or emergencyAdmin

Standard Withdraw

Target:   [STRATEGY_ADDRESS]
Function: withdraw(uint256,address,address)
Selector: 0xb460af94
Value:    0

Parameters:
  assets:   Amount of wstETH to withdraw
  receiver: Address to receive wstETH
  owner:    0xb1a32FC9F9D8b2cf86C068Cae13108809547ef71 (Treasury)

Note: Can be called anytime, no lockup period.

Quick Reference: Function Selectors

Function Selector Target Purpose
createPaymentSplitter(...)TBDPaymentSplitter FactoryDeploy splitter
createStrategy(...)TBDLidoStrategy FactoryDeploy strategy
approve(address,uint256)0x095ea7b3wstETHAllow spending
deposit(uint256,address)0x6e553f65StrategyDeposit funds
withdraw(uint256,address,address)0xb460af94StrategyWithdraw funds
report()0x2606a10bStrategyHarvest yield
shutdownStrategy()0xbe8f1668StrategyEmergency shutdown
emergencyWithdraw(uint256)0x5312ea8eStrategyEmergency exit

Operational Considerations

Keeper Setup

See Role Assignments for Keeper requirements. A dedicated EOA or bot enables autonomous harvesting without governance votes.

Recommended: Set up a keeper bot to call report() periodically (e.g., weekly or monthly) to:

  1. Update accounting
  2. Mint yield shares to Dragon Router
  3. Keep exchange rate tracking accurate

Emergency Admin

The Treasury serves as Emergency Admin. Emergency actions (shutdown, forced withdrawals) will follow standard DAO voting timelines (~7 days) unless a separate multisig is designated for faster response.

Withdrawals

The strategy provides instant liquidity (no lockup). Withdrawals are straightforward:

  1. Call withdraw(assets, receiver, owner) or redeem(shares, receiver, owner) on the strategy
  2. Receive underlying wstETH immediately

No unwinding of positions is needed — wstETH is held directly.

Value Debt Tracking

The strategy uses a dual-debt accounting system:

  • User Debt: Tracks ETH value owed to depositors
  • Dragon Debt: Tracks ETH value owed to Dragon Router (yield recipient)

This ensures:

  • Users can always redeem their original value
  • Dragon Router only receives actual profit
  • Insolvency protection: Dragon operations blocked if vault can't cover user debt

Treasury Holdings (Reference)

Current Nouns DAO treasury holdings (as of snapshot):

Asset Amount Value (USD)
wstETH ~1,725 ~$6.7M
rETH ~163 ~$600k
USDC ~726k ~$726k
ETH ~517 ~$1.6M

Source: Etherscan Treasury

References